#ifndef __MGGS_POINT__
#define __MGGS_POINT__


#include <initializer_list>
#include <iostream>
#include <eigen/Eigen/Dense>

using namespace Eigen;

template <typename T, int DIM>
class Point{
private:
  Vector<T,DIM> coord;
  int index;
  int boundary_mark;
public:
  Point();
  Point(const std::initializer_list<T> _com_list, const int _index, const int _boundary);
  void set_coord(const std::initializer_list<T> _com_list);
  Vector<T,DIM> get_coord() const;
  T get_coord(const int _i) const;
  void set_index(const int _index);
  int get_index() const;
  void set_boundary_mark(const int _boundary);
  int get_boundary_mark() const;
};

template <typename T, int DIM>
Point<T,DIM>::Point(){
  coord.setZero(DIM,1);
  index = -1;
  boundary_mark = -1;
}

template <typename T, int DIM>
Point<T,DIM>::Point(const std::initializer_list<T> _com_list, const int _index, const int _boundary){
  this->set_coord(_com_list);
  index = _index;
  boundary_mark = _boundary;
}

template <typename T, int DIM>
void Point<T,DIM>::set_coord(const std::initializer_list<T> _com_list){
  if (_com_list.size() == DIM){
    int count = 0;
    for(auto it=_com_list.begin();it!=_com_list.end();++it){
      coord(count) = *it;
      count++;
    }
  }
  else
    std::cerr << "No match for dimension!" << std::endl;
}

template <typename T, int DIM>
Vector<T,DIM> Point<T,DIM>::get_coord() const{
  return coord;
}

template <typename T, int DIM>
T Point<T,DIM>::get_coord(const int _i) const{
  if (_i < DIM)
    return coord(_i);
  else{
    std::cerr << "Out of bound!" << std::endl;
    return 0;
  } 
}

template <typename T, int DIM>
void Point<T,DIM>::set_index(const int _index){
  index = _index;
}

template <typename T, int DIM>
int Point<T,DIM>::get_index() const{
  return index;
}

template <typename T, int DIM>
void Point<T,DIM>::set_boundary_mark(const int _boundary){
  boundary_mark = _boundary;
}

template <typename T, int DIM>
int Point<T,DIM>::get_boundary_mark() const{
  return boundary_mark;
}

#else
// DO NOTHING.
#endif
